package com.aliyun.messagemgt.application.service.Impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.messagemgt.common.dto.send.MsgMiddleResult;
import com.aliyun.messagemgt.common.dto.send.MsgPushDTO;
import com.aliyun.messagemgt.common.dto.send.MsgRecordVO;
import com.aliyun.messagemgt.common.dto.send.Receiver;
import com.aliyun.messagemgt.application.service.BaseReceiveGroupService;
import com.aliyun.messagemgt.application.service.ReceiverHandle;
import com.aliyun.messagemgt.common.enums.RangeTypeEnum;
import com.aliyun.messagemgt.convert.FouraConverter;
import com.aliyun.messagemgt.common.errorcode.push.CommonErrorCode;
import com.aliyun.messagemgt.common.exceptions.BaseException;
import com.aliyun.messagemgt.fouraplugin.FouraService;
import com.aliyun.messagemgt.domain.repository.ISysUserInfoService;
import com.aliyun.messagemgt.dto.base.BaseReceiveGroupDetailDTO;
import com.aliyun.messagemgt.dto.base.BaseReceiveGroupRangeDTO;
import com.aliyun.messagemgt.common.dto.foura.FouraOrgUserInfoDTO;
import com.aliyun.messagemgt.common.dto.foura.FouraPositionUserInfoDTO;
import com.aliyun.messagemgt.common.dto.foura.FouraRoleUserInfoDTO;
import com.aliyun.messagemgt.common.dto.foura.FouraUserInfoDTO;
import com.aliyun.messagemgt.common.dto.foura.FouraGetUserByOrgQry;
import com.aliyun.messagemgt.common.dto.foura.FouraPositionUserQry;
import com.aliyun.messagemgt.common.dto.foura.FouraRoleUserQry;
import com.aliyun.messagemgt.common.dto.foura.FouraUserQry;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created with IDEA
 *
 * @author:zhangxingxing 0027012120
 * @date:2019/2/22
 * @time:10:20
 */
@Component
public class ReceiverHandleImpl implements ReceiverHandle {

//    @Value("${4A.cas.version}")
//    private Integer version;
//    @Value("${4A.cas.appCode}")
//    private String appCode;
//    @Value("${4A.cas.name}")
//    private String name;
//    @Value("${4A.cas.password}")
//    private String password;
//    @Value("${4A.cas.user.url}")
//    private String userUrl;

    private static final String USER_CODE = "userCode";

    private static final Logger logger = LoggerFactory.getLogger(ReceiverHandle.class);

    @Autowired
    private BaseReceiveGroupService baseReceiveGroupService;
    @Autowired
    private FouraService fouraService;
    @Autowired
    private ISysUserInfoService sysUserInfoService;
//    /**
//     * 1.类型判断
//     * 2. 不是推送到端的类型都为
//     * 3. 组织解析
//     * 4. 人员去重
//     *
//     * @param msgRecordVos
//     */
//    @Override
//    public void receiverCal(List<MsgRecordVO> msgRecordVos) {
//        for (MsgRecordVO msgRecordVO : msgRecordVos) {
//            List<MsgMiddleResult> results = msgRecordVO.getResults();
//            List<FourAObjectEntity> users = msgRecordVO.getPushUserIds();
//            List<FourAObjectEntity> orgs = msgRecordVO.getPushOrgIds();
//            Integer pushLabelId = msgRecordVO.getPushLabelId();
//            // users 或 orgs 为空则为渠道推送
//            List<Receiver> receivers = new ArrayList<>();
//            // 虽然现在场景只有users或者orgs的情况 ，但是可能以后会存在users或者orgs都有的情况
//            boolean hasUser = users != null && users.size() > 0;
//            if (hasUser) {
//                for (FourAObjectEntity user : users) {
//                    receivers.add(new Receiver().setReceiverType(String.valueOf(PushConstant.USER_RECEIVER))
//                            .setReceiverId(user.getKey())
//                            .setReceiverName(user.getName()));
//                }
//            }
//            boolean hasOrg = orgs != null && orgs.size() > 0;
//            if (hasOrg) {
//                receivers.addAll(orgResolve(orgs, results));
//            }
//            if (pushLabelId != null) {
//                receivers.addAll(labelIdResolve(pushLabelId));
//            }
//            if (!hasUser && !hasOrg && pushLabelId == null) {
//                receivers.add(new Receiver().setReceiverType(String.valueOf(PushConstant.CHANNEL_RECEIVER))
//                        .setReceiverId(String.valueOf(msgRecordVO.getPushChannelId()))
//                        .setReceiverName(msgRecordVO.getPushChannelName()));
//            }
//            receivers = receiverFilter(receivers);
//            logger.info("receiverCal receiver {}", receivers.toString());
//            msgRecordVO.setReceivers(receivers);
//            msgRecordVO.setResults(results);
//        }
//    }

    /**
     * 1.类型判断
     * 2. 组织、角色、岗位等解析
     * 3. 人员去重
     *
     * @param msgRecordVos
     */
    @Override
    public void receiverCalNew(List<MsgRecordVO> msgRecordVos) {
        for (MsgRecordVO msgRecordVO : msgRecordVos) {
            List<MsgMiddleResult> results = msgRecordVO.getResults();
            MsgPushDTO.MsgRecordDTO.ReceiveRangeInfo receiveRangeInfo = msgRecordVO.getReceiveRangeInfo();
            logger.info("receiverCalNew receiveRangeInfo:{}",receiveRangeInfo);
            // 1.转换为最终去查询用户的数据结构,key ->  rangeType，value -> idList
            Map<String, List<String>> map = new HashMap<>();
            if ("GROUP".equals(receiveRangeInfo.getRangeTransType())) {
                //按接收组传(多个分组，rangeEntityId是json数组对象)
                List<BaseReceiveGroupDetailDTO> baseReceiveGroupDetailDTOList = baseReceiveGroupService.selectList(msgRecordVO.getTenantCode(), receiveRangeInfo.getReceiveGroupCodes());
                baseReceiveGroupDetailDTOList.forEach(
                        baseReceiveGroupDetailDTO -> {
                            List<BaseReceiveGroupRangeDTO> baseReceiveGroupRangeDTOS = baseReceiveGroupDetailDTO.getBaseReceiveGroupRangeDTOList();
                            baseReceiveGroupRangeDTOS.forEach(
                                    baseReceiveGroupRangeDTO -> {
                                        String rangeType = baseReceiveGroupRangeDTO.getRangeType();
                                        // 消息组件后台接收组为USER时发送消息类型需转为为USERID,消息发送用户范围除了USERID还有手机号和邮箱;
                                        if("USER".equals(rangeType)){
                                            rangeType = RangeTypeEnum.USERID.getCode();
                                        }
                                        String rangeEntityId = baseReceiveGroupRangeDTO.getRangeEntityId();
                                        List<JSONObject> jsonObjectList = JSON.parseArray(rangeEntityId, JSONObject.class);
                                        List<String> ids = jsonObjectList.stream().map(
                                                jsonObject -> jsonObject.keySet().iterator().next()
                                        ).collect(Collectors.toList());
                                        List<String> idList = map.get(rangeType);
                                        if (CollectionUtils.isEmpty(idList)) {
                                            idList = new ArrayList<>();
                                        }
                                        idList.addAll(ids);
                                        map.put(rangeType, idList);
                                    }
                            );
                        }
                );
            } else {
                // 按范围自定义(单个分组，rangeEntityId是String数组)
                map.put(receiveRangeInfo.getRangeType(), receiveRangeInfo.getRangeValues());
            }
            logger.info("receiverCalNew 查询用户前map:{}",map);
            // 2.去用户组件侧查询用户信息
            List<Receiver> receivers = processReceivers(map, msgRecordVO);
            receivers = receiverFilter(receivers);
            // 3.手机号单独处理
            processCustomerPhoneReceivers(receivers, msgRecordVO);
            // 4.邮箱单独处理
            processCustomerEmailReceivers(receivers, msgRecordVO);
            // 5.工号单独处理
            processCustomerEmployeeCodeReceivers(receivers, msgRecordVO);
            logger.info("receiverCalNew receivers {}", receivers);
            if (CollectionUtils.isEmpty(receivers)) {
                throw new BaseException(CommonErrorCode.RECEIVERANGE_IS_EMPTY);
            }
            msgRecordVO.setReceivers(receivers);
            msgRecordVO.setResults(results);
        }
    }

    private void processCustomerEmployeeCodeReceivers(List<Receiver> receivers, MsgRecordVO msgRecordVO) {
        MsgPushDTO.MsgRecordDTO.ReceiveRangeInfo receiveRangeInfo = msgRecordVO.getReceiveRangeInfo();
        String rangeTransType = receiveRangeInfo.getRangeTransType();
        String rangeType = receiveRangeInfo.getRangeType();
        if ("CUST".equals(rangeTransType) && RangeTypeEnum.EMPLOYEECODE.getCode().equals(rangeType)
                && CollectionUtils.isNotEmpty(receiveRangeInfo.getRangeValues())) {
            Set<String> receiverEmployeeCodes = receivers.stream().map(Receiver::getEmployeeCode).collect(Collectors.toSet());
            Set<String> rangeValues = receiveRangeInfo.getRangeValues().stream()
                    .filter(value -> StringUtils.isNotBlank(value)).collect(Collectors.toSet());
            rangeValues.stream().forEach(
                    rangeValue -> {
                        if (!receiverEmployeeCodes.contains(rangeValue)) {
                            Receiver receiver = new Receiver();
                            receiver.setReceiverType(RangeTypeEnum.EMPLOYEECODE.getCode());
                            receiver.setEmployeeCode(rangeValue);
                            receivers.add(receiver);
                        }
                    }
            );
        }
    }

    private void processCustomerPhoneReceivers(List<Receiver> receivers, MsgRecordVO msgRecordVO) {
        MsgPushDTO.MsgRecordDTO.ReceiveRangeInfo receiveRangeInfo = msgRecordVO.getReceiveRangeInfo();
        String rangeTransType = receiveRangeInfo.getRangeTransType();
        String rangeType = receiveRangeInfo.getRangeType();
        if ("CUST".equals(rangeTransType) && RangeTypeEnum.PHONE.getCode().equals(rangeType)
                && CollectionUtils.isNotEmpty(receiveRangeInfo.getRangeValues())) {
            Set<String> receiverMobilePhones = receivers.stream().map(Receiver::getReceiverMobilePhone).collect(Collectors.toSet());
            Set<String> rangeValues = receiveRangeInfo.getRangeValues().stream()
                    .filter(value -> StringUtils.isNotBlank(value)).collect(Collectors.toSet());
            rangeValues.stream().forEach(
                    rangeValue -> {
                        if (!receiverMobilePhones.contains(rangeValue)) {
                            Receiver receiver = new Receiver();
                            receiver.setReceiverType(RangeTypeEnum.PHONE.getCode());
                            receiver.setReceiverMobilePhone(rangeValue);
                            receivers.add(receiver);
                        }
                    }
            );
        }
    }
    private void processCustomerEmailReceivers(List<Receiver> receivers, MsgRecordVO msgRecordVO) {
        MsgPushDTO.MsgRecordDTO.ReceiveRangeInfo receiveRangeInfo = msgRecordVO.getReceiveRangeInfo();
        String rangeTransType = receiveRangeInfo.getRangeTransType();
        String rangeType = receiveRangeInfo.getRangeType();
        if ("CUST".equals(rangeTransType) && RangeTypeEnum.EMAIL.getCode().equals(rangeType)
                && CollectionUtils.isNotEmpty(receiveRangeInfo.getRangeValues())) {
            Set<String> receiverEmails = receivers.stream().map(Receiver::getReceiverEmail).collect(Collectors.toSet());
            Set<String> rangeValues = receiveRangeInfo.getRangeValues().stream()
                    .filter(value -> StringUtils.isNotBlank(value)).collect(Collectors.toSet());
            rangeValues.stream().forEach(
                    rangeValue -> {
                        if (!receiverEmails.contains(rangeValue)) {
                            Receiver receiver = new Receiver();
                            receiver.setReceiverType(RangeTypeEnum.EMAIL.getCode());
                            receiver.setReceiverEmail(rangeValue);
                            receivers.add(receiver);
                        }
                    }
            );
        }
    }

    /**
     * 去用户组件侧查询用户信息,key ->  rangeType，value -> idList
     *
     * @param map
     * @return
     */
    private List<Receiver> processReceivers(Map<String, List<String>> map, MsgRecordVO msgRecordVO) {
        String tenantCode = msgRecordVO.getTenantCode();
        // 存放最终接收者,并去重
        Map<String, Receiver> receiverMap = new HashMap<>();
        map.forEach((rangeType, idList) -> {
            idList = idList.stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
            // idList为空的话跳过循环
            if (CollectionUtils.isEmpty(idList)) {
                return;
            }
            List<Long> ids = null;
            // 邮箱类型的rangeValues不需要转换
            if (!RangeTypeEnum.EMAIL.getCode().equals(rangeType)) {
                try {
                    ids = idList.stream().map(Long::valueOf).collect(Collectors.toList());
                } catch (Exception e) {
                    logger.error("rangeValues错误，e:{}", e);
                }
            }
            List<FouraUserInfoDTO> fouraUserInfoDTOS = null;
            String receiverType = null;
            try {
                // 组织类型
                if (RangeTypeEnum.ORG.getCode().equals(rangeType)) {
                    FouraGetUserByOrgQry qry = new FouraGetUserByOrgQry();
                    qry.setOrgIdList(idList);
                    qry.setAppCode(tenantCode);
                    List<FouraOrgUserInfoDTO> fouraOrgUserInfoDTOS = fouraService.selectUserByOrg(qry);
                    fouraUserInfoDTOS = FouraConverter.INSTANCE.fouraOrgUserInfoDTOS2fouraUserInfoDTOS(fouraOrgUserInfoDTOS);
                    receiverType = RangeTypeEnum.USERID.getCode();
                }
                // 岗位类型
                if (RangeTypeEnum.POS.getCode().equals(rangeType) && CollectionUtils.isNotEmpty(ids)) {
                    FouraPositionUserQry qry = new FouraPositionUserQry();
                    qry.setAppCode(tenantCode);
                    qry.setPositionIdList(ids);
                    List<FouraPositionUserInfoDTO> fouraPositionUserInfoDTOS = fouraService.qryUserListByPositionId(qry);
                    fouraUserInfoDTOS = FouraConverter.INSTANCE.fouraPositionUserInfoDTOS2fouraUserInfoDTOS(fouraPositionUserInfoDTOS);
                    receiverType = RangeTypeEnum.USERID.getCode();
                }
                // 角色类型
                if (RangeTypeEnum.ROLE.getCode().equals(rangeType) && CollectionUtils.isNotEmpty(ids)) {
                    FouraRoleUserQry qry = new FouraRoleUserQry();
                    qry.setAppCode(tenantCode);
                    qry.setRoleIdList(ids);
                    List<FouraRoleUserInfoDTO> fouraRoleUserInfoDTOS = fouraService.selectUserListByRoleIdListOrAppCodeList(qry);
                    fouraUserInfoDTOS = FouraConverter.INSTANCE.fouraRoleUserInfoDTOS2fouraUserInfoDTOS(fouraRoleUserInfoDTOS);
                    receiverType = RangeTypeEnum.USERID.getCode();
                }
                // 用户类型
                if (RangeTypeEnum.USERID.getCode().equals(rangeType) && CollectionUtils.isNotEmpty(ids)) {
                    FouraUserQry qry = new FouraUserQry();
                    qry.setAppCode(tenantCode);
                    qry.setUserIdList(ids);
                    fouraUserInfoDTOS = fouraService.qryUserInfoByUserListOrAppCode(qry);
                    receiverType = RangeTypeEnum.USERID.getCode();
                }
                // 手机号类型
                if (RangeTypeEnum.PHONE.getCode().equals(rangeType)) {
                    FouraUserQry qry = new FouraUserQry();
                    qry.setAppCode(tenantCode);
                    qry.setMobilephoneList(idList);
                    fouraUserInfoDTOS = fouraService.qryUserInfoByUserListOrAppCode(qry);
                    receiverType = RangeTypeEnum.PHONE.getCode();
                }
                // 邮件类型
                if (RangeTypeEnum.EMAIL.getCode().equals(rangeType)) {
                    FouraUserQry qry = new FouraUserQry();
                    qry.setAppCode(tenantCode);
                    qry.setEmailList(idList);
                    fouraUserInfoDTOS = fouraService.qryUserInfoByUserListOrAppCode(qry);
                    receiverType = RangeTypeEnum.EMAIL.getCode();
                }
                // 员工工号类型
                if (RangeTypeEnum.EMPLOYEECODE.getCode().equals(rangeType)) {
                    FouraUserQry qry = new FouraUserQry();
                    qry.setAppCode(tenantCode);
                    qry.setEmployeeCodeList(idList);
                    fouraUserInfoDTOS = fouraService.qryUserInfoByUserListOrAppCode(qry);
                    receiverType = RangeTypeEnum.EMPLOYEECODE.getCode();
                }
            } catch (Exception e) {
                logger.error("{},错误详情：{}", CommonErrorCode.FEIGN_EXCEPTION.errName(), e);
                throw new BaseException(CommonErrorCode.FEIGN_EXCEPTION);
            }
            String finalReceiverType = receiverType;
            if (CollectionUtils.isNotEmpty(fouraUserInfoDTOS)) {
                fouraUserInfoDTOS.stream().filter(Objects::nonNull).forEach(
                        fouraUserInfoDTO -> {
                            Receiver receiver = new Receiver();
                            receiver.setReceiverType(finalReceiverType);
                            String userId = fouraUserInfoDTO.getUserId().toString();
                            receiver.setReceiverId(userId);
                            receiver.setReceiverMobilePhone(fouraUserInfoDTO.getMobilePhone());
                            receiver.setReceiverEmail(fouraUserInfoDTO.getEmail());
                            receiver.setEmployeeCode(fouraUserInfoDTO.getEmployeeCode());
                            receiver.setReceiverName(fouraUserInfoDTO.getUserName());
                            receiverMap.put(userId, receiver);
                        }
                );
            }
        });
        return new ArrayList<>(receiverMap.values());
    }

//    private List<SysUserInfoDTO> processDingTalkUserIdList(MsgRecordVO msgRecordVO) {
//        String tenantCode = msgRecordVO.getTenantCode();
//        List<String> mobilePhones = msgRecordVO.getReceivers().stream().map(Receiver::getReceiverMobilePhone).collect(Collectors.toList());
//        List<SysUserInfoDTO> normalSysUserInfoList = new ArrayList<>();
//        List<SysUserInfoDTO> sysUserInfoList = sysUserInfoService.getUserIdByMobile(mobilePhones);
//        List<String> ids = new ArrayList<>();
//        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(sysUserInfoList)) {
//            // 查询出的所有手机号码
//            List<String> mobilePhoneList = sysUserInfoList.stream().map(
//                    sysUserInfoDTO -> {
//                        ids.add(sysUserInfoDTO.getUserId());
//                        return sysUserInfoDTO.getMobilePhone();
//                    }
//            ).collect(Collectors.toList());
//            normalSysUserInfoList.addAll(sysUserInfoList);
//            // 求差集-没有对应用户信息的手机号
//            mobilePhones.removeAll(mobilePhoneList);
//        }
//        // 求差集后如果userIds不为空，则调用api查询，查询后存入数据库
//        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(mobilePhones)) {
//            List<Receiver> receivers = new ArrayList<>();
//            List<String> mobilePhoneList = new ArrayList<>();
//            List<SysUserInfoDTO> noSyncUserInfoList = new ArrayList<>();
//            DingTalkMobileDTO dingTalkMobileDTO = new DingTalkMobileDTO();
//            dingTalkMobileDTO.setAppKey();
//            for (String mobilePhone : mobilePhones) {
//                String id = DingTalkUtils.getUserIdByMobile(mobilePhone, token);
//                if (StringUtils.isNotEmpty(id)) {
//                    ids.add(id);
//                    SysUserInfoDTO sysUserInfoDTO = new SysUserInfoDTO();
//                    sysUserInfoDTO.setUserId(id);
//                    sysUserInfoDTO.setMobilePhone(mobilePhone);
//                    sysUserInfoDTO.setTenantCode(tenantCode);
//                    sysUserInfoDTO.setCreator("admin");
//                    sysUserInfoDTO.setModifier("admin");
//                    noSyncUserInfoList.add(sysUserInfoDTO);
//                } else {
//                    receivers.add(new Receiver().setReceiverType(RangeTypeEnum.PHONE.getCode())
//                            .setReceiverMobilePhone(mobilePhone));
//                    mobilePhoneList.add(mobilePhone);
//                }
//                if (org.apache.commons.collections.CollectionUtils.isNotEmpty(receivers)) {
//                    MsgMiddleResult msgMiddleResult = new MsgMiddleResult()
//                            .setReceivers(receivers)
//                            .setPushResultCode(PushResultEnum.PUSH_DINGTALK_USER_NOTEXIT.getErrorCode())
//                            .setPushResultDescription(PushResultEnum.PUSH_DINGTALK_USER_NOTEXIT.getDescription() + ":" + mobilePhone);
//                    msgRecordVO.getResults().add(msgMiddleResult);
//                    List<Receiver> receivers1 = msgRecordVO.getReceivers();
//                    receivers1 = receivers1.stream().filter(
//                            receiver -> {
//                                if (mobilePhoneList.contains(receiver.getReceiverMobilePhone())) {
//                                    return false;
//                                }
//                                return true;
//                            }
//                    ).collect(Collectors.toList());
//                    msgRecordVO.setReceivers(receivers1);
//                }
//            }
//            if (org.apache.commons.collections.CollectionUtils.isNotEmpty(noSyncUserInfoList)) {
//                sysUserInfoService.batchInsert(noSyncUserInfoList);
//                normalSysUserInfoList.addAll(noSyncUserInfoList);
//            }
//        }
//        return normalSysUserInfoList;
//    }

//    private List<Receiver> labelIdResolve(Integer pushLabelId) {
//        List<Receiver> labelUserList = new ArrayList<>();
//        String userLabel = pushLabelRepository.queryUserLabel(pushLabelId);
//        if (!StringUtils.isEmpty(userLabel)) {
//            List<FourAObjectEntity> fouraObjectEntities = JSONArray.parseArray(userLabel, FourAObjectEntity.class);
//            for (FourAObjectEntity fouraObjectEntity : fouraObjectEntities) {
//                Receiver receiver = new Receiver().setReceiverName(fouraObjectEntity.getName())
//                        .setReceiverId(fouraObjectEntity.getKey())
//                        .setReceiverType(String.valueOf(PushConstant.LABEL_RECEIVER));
//                labelUserList.add(receiver);
//            }
//        }
//        return labelUserList;
//    }

//    /**
//     * 组织解析,如果解析失败，把失败的数据放到msgMiddleResults中
//     *
//     * @return
//     */
//    private List<Receiver> orgResolve(List<FourAObjectEntity> orgs, List<MsgMiddleResult> msgMiddleResults) {
//        List<Receiver> users = new ArrayList<>();
//        return users;
//    }

    /**
     * receiver过滤 -> 名单过滤（@all） -> 去重
     *
     * @param receivers
     * @return
     */
    private List<Receiver> receiverFilter(List<Receiver> receivers) {
        Set<Receiver> set = new HashSet<>();
        List<Receiver> newList = new ArrayList<>();
        for (Receiver receiver : receivers) {
            String receiverId = receiver.getReceiverId();
            String receiverMobilePhone = receiver.getReceiverMobilePhone();
            String receiverEmail = receiver.getReceiverEmail();
            String employeeCode = receiver.getEmployeeCode();
            boolean hashValue = false;
            // 不同渠道所需接收人参数不同，兼容多种渠道
            if (StringUtils.isNotBlank(receiverId)
                    || StringUtils.isNotBlank(receiverMobilePhone)
                    || StringUtils.isNotBlank(receiverEmail)
                    || StringUtils.isNotBlank(employeeCode)) {
                hashValue = true;
            }
            // 过滤@all
            if (!"@all".equalsIgnoreCase(receiverId)
                    && !"@all".equalsIgnoreCase(receiverMobilePhone)
                    && hashValue) {
                set.add(receiver);
            }
        }
        newList.addAll(set);
        return newList;
    }

}
